home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 1 / Cream of the Crop 1.iso / PROGRAM / INDENT3.ARJ / IO.C < prev    next >
C/C++ Source or Header  |  1992-08-04  |  14KB  |  541 lines

  1. /*
  2.  * Copyright (c) 1980 Regents of the University of California. All rights
  3.  * reserved.  The Berkeley software License Agreement specifies the terms and
  4.  * conditions for redistribution. 
  5.  */
  6.  
  7. #ifndef lint
  8. static char sccsid[] = "@(#)io.c    5.2 (Berkeley) 8/28/85";
  9. #endif not lint
  10.  
  11. /*-
  12.  *              Copyright (C) 1976
  13.  *                by the
  14.  *              Board of Trustees
  15.  *                of the
  16.  *            University of Illinois
  17.  *             All rights reserved
  18.  * FILE NAME:
  19.  *    io.c
  20.  * PURPOSE:
  21.  *    Contains routines to handle i/o related stuff for indent.
  22.  * GLOBALS:
  23.  *    None
  24.  * FUNCTIONS:
  25.  *    dump_line
  26.  *    fill_buffer
  27.  *    pad_output
  28.  *    count_spaces
  29.  *    eqin
  30.  *    cmp
  31.  *
  32.  */
  33. /*-
  34.  *
  35.  *              Copyright (C) 1976
  36.  *                by the
  37.  *              Board of Trustees
  38.  *                of the
  39.  *            University of Illinois
  40.  *
  41.  *             All rights reserved
  42.  *
  43.  *
  44.  * NAME:
  45.  *    dump_line
  46.  *
  47.  * FUNCTION:
  48.  *    Does the actual printing of the stored up line
  49.  *
  50.  * ALGORITHM:
  51.  *    For each of the label, code, and comment sections which are used on 
  52.  *    this line:
  53.  *
  54.  *    1) Use pad_output to get the section aligned properly.
  55.  *    2) write the section
  56.  *
  57.  *    The indentation level used for the code is set by ps.ind_level.  After
  58.  *    printing, ps.ind_level is set to ps.i_l_follow.
  59.  *
  60.  *    An extra level of indentation is added if ps.ind_stmt is 1.  After 
  61.  *    printing, ps.ind_stmt is set to 1 iff the line just printed has an
  62.  *    unterminated, non-declaration statement.
  63.  *
  64.  * HISTORY:
  65.  *    initial coding     November 1976    D A Willcox of CAC
  66.  *
  67.  */
  68. #include "indent_globs.h"
  69.  
  70. int ff = '\f';            /* used to write a form feed */
  71. int comment_open;
  72. static paren_target;
  73.  
  74. void dump_line()
  75. {                /* dump_line is the routine that actually
  76.                  * effects the printing of the new source. It
  77.                  * prints the label section, followed by the
  78.                  * code section with the appropriate nesting
  79.                  * level, followed by any comments */
  80.     register int cur_col, temp_col, target_col;
  81.  
  82.     if (ps.procname[0]) {
  83.     if (troff)
  84.         fprintf(output, ".Pr \"%s\"\n", ps.procname);
  85.     ps.ind_level = 0;
  86.     ps.procname[0] = 0;
  87.     }
  88.     if (s_code == e_code && s_lab == e_lab && s_com == e_com) {
  89.     if (suppress_blanklines > 0)
  90.         suppress_blanklines--;
  91.     else {
  92.         ps.bl_line = true;
  93.         n_real_blanklines++;
  94.     }
  95.     } else if (!inhibit_formatting) {
  96.     suppress_blanklines = 0;
  97.     ps.bl_line = false;
  98.     if (prefix_blankline_requested)
  99.         if (swallow_optional_blanklines) {
  100.         if (n_real_blanklines == 1)
  101.             n_real_blanklines = 0;
  102.         } else {
  103.         if (n_real_blanklines == 0)
  104.             n_real_blanklines = 1;
  105.         }
  106.     while (--n_real_blanklines >= 0)
  107.         putc('\n', output);
  108.     n_real_blanklines = 0;
  109.     if (ps.ind_level == 0)
  110.         ps.ind_stmt = 0;    /* this is a class A kludge. dont do
  111.                  * additional statement indentation if we are
  112.                  * at bracket level 0 */
  113.  
  114.     if (e_lab != s_lab || e_code != s_code)
  115.         ++code_lines;    /* keep count of lines with code */
  116.  
  117.  
  118.     if (e_lab != s_lab) {    /* print lab, if any */
  119.         if (comment_open) {
  120.         comment_open = 0;
  121.         fprintf(output, ".*/\n");
  122.         }
  123.         while (e_lab > s_lab && (e_lab[-1] == ' ' || e_lab[-1] == '\t'))
  124.         e_lab--;
  125.         cur_col = pad_output(1, compute_label_target());
  126.         fprintf(output, "%.*s", e_lab - s_lab, s_lab);
  127.         cur_col = count_spaces(cur_col, s_lab);
  128.     } else
  129.         cur_col = 1;    /* there is no label section */
  130.  
  131.     ps.pcase = false;
  132.  
  133.     if (s_code != e_code) {    /* print code section, if any */
  134.         register char *p;
  135.  
  136.         if (comment_open) {
  137.         comment_open = 0;
  138.         fprintf(output, ".*/\n");
  139.         }
  140.         target_col = compute_code_target();
  141.         {
  142.         register i;
  143.  
  144.         for (i = 0; i < ps.p_l_follow; i++)
  145.             if (ps.paren_indents[i] >= 0)
  146.             ps.paren_indents[i] = -(ps.paren_indents[i] + target_col);
  147.         }
  148.         cur_col = pad_output(cur_col, target_col);
  149.         for (p = s_code; p < e_code; p++)
  150.         if (*p == 0200)
  151.             fprintf(output, "%d", target_col * 7);
  152.         else
  153.             putc(*p, output);
  154.         cur_col = count_spaces(cur_col, s_code);
  155.     }
  156.     if (s_com != e_com)
  157.         if (troff) {
  158.         register char *p;
  159.  
  160.         if (e_com[-1] == '/' && e_com[-2] == '*')
  161.             e_com -= 2;
  162.         while (e_com > s_com && e_com[-1] == ' ')
  163.             e_com--;
  164.         *e_com = 0;
  165.         p = s_com;
  166.         while (*p == ' ')
  167.             p++;
  168.         if (p[0] == '/' && p[1] == '*')
  169.             p += 2;
  170.         else if (p[0] == '*')
  171.             p += p[1] == '/' ? 2 : 1;
  172.         while (*p == ' ')
  173.             p++;
  174.         if (*p == 0)
  175.             goto inhibit_newline;
  176.         if (!comment_open) {
  177.             if ('a' <= *p && *p <= 'z')
  178.             *p = *p + 'A' - 'a';
  179.             if (s_code != e_code || s_lab != e_lab) {
  180.             fprintf(output, "\\c\n./* %dp 1 %dp\n",
  181.                 ps.com_col * 7, target_col * 7);
  182.             } else
  183.             fprintf(output, "./* %dp 0 %dp\n",
  184.                 ps.com_col * 7, target_col * 7);
  185.         }
  186.         comment_open = 1;
  187.         while (*p) {
  188.             if (*p == BACKSLASH)
  189.             putc(BACKSLASH, output);
  190.             putc(*p++, output);
  191.         }
  192.         } else {        /* print comment, if any */
  193.         register target = ps.com_col;
  194.         register char *com_st = s_com;
  195.  
  196.         target += ps.comment_delta;
  197.         while (target <= 0)
  198.             if (*s_com == ' ')
  199.             target++, s_com++;
  200.             else if (*s_com == '\t') {
  201.             /* target = ((target - 1) & ~7) + 9; */
  202.             target += tabsize - (target % tabsize) + 1;
  203.             s_com++;
  204.             } else
  205.             target = 1;
  206.         if (cur_col > target) {        /* if comment cant fit on
  207.                          * this line, put it on next
  208.                          * line */
  209.             putc('\n', output);
  210.             cur_col = 1;
  211.             ++ps.out_lines;
  212.         }
  213.         cur_col = pad_output(cur_col, target);
  214.         if (!ps.box_com) {
  215.             if (star_comment_cont && com_st[1] != '*')
  216.             if (com_st[1] == ' ' && com_st[0] == ' ')
  217.                 com_st[1] = '*';
  218.             else
  219.                 fwrite(" * ", com_st[0] == '\t' ? 2 : com_st[0] == '*' ? 1 : 3, 1, output);
  220.         }
  221.         fwrite(com_st, e_com - com_st, 1, output);
  222.         ps.comment_delta = ps.n_comment_delta;
  223.         cur_col = count_spaces(cur_col, com_st);
  224.         ++ps.com_lines;    /* count lines with comments */
  225.         }
  226.     if (ps.use_ff)
  227.         putc('\f', output);
  228.     else
  229.         putc('\n', output);
  230. inhibit_newline:
  231.     ++ps.out_lines;
  232.     if (ps.just_saw_decl == 1 && blanklines_after_declarations) {
  233.         prefix_blankline_requested = 1;
  234.         ps.just_saw_decl = 0;
  235.     } else
  236.         prefix_blankline_requested = postfix_blankline_requested;
  237.     postfix_blankline_requested = 0;
  238.     }
  239.     ps.decl_on_line = ps.in_decl;    /* if we are in the middle of a
  240.                      * declaration, remember that fact
  241.                      * for proper comment indentation */
  242.     ps.ind_stmt = ps.in_stmt & ~ps.in_decl;    /* next line should be
  243.                          * indented if we have not
  244.                          * completed this stmt and if
  245.                          * we are not in the middle
  246.                          * of a declaration */
  247.     ps.use_ff = false;
  248.     ps.dumped_decl_indent = 0;
  249.     *(e_lab = s_lab) = '\0';    /* reset buffers */
  250.     *(e_code = s_code) = '\0';
  251.     *(e_com = s_com) = '\0';
  252.     ps.ind_level = ps.i_l_follow;
  253.     ps.paren_level = ps.p_l_follow;
  254.     paren_target = -ps.paren_indents[ps.paren_level - 1];
  255.     return;
  256. };
  257.  
  258. compute_code_target()
  259. {
  260.     register target_col = ps.ind_size * ps.ind_level + 1;
  261.  
  262.     if (ps.paren_level)
  263.     if (!lineup_to_parens)
  264.         target_col += continuation_indent * ps.paren_level;
  265.     else {
  266.         register w;
  267.         register t = paren_target;
  268.  
  269.         if ((w = count_spaces(t, s_code) - max_col) > 0
  270.         && count_spaces(target_col, s_code) <= max_col) {
  271.         t -= w + 1;
  272.         if (t > target_col)
  273.             target_col = t;
  274.         } else
  275.         target_col = t;
  276.     }
  277.     else if (ps.ind_stmt)
  278.     target_col += continuation_indent;
  279.     return target_col;
  280. }
  281.  
  282. compute_label_target()
  283. {
  284.     return
  285.     ps.pcase ? (int) (case_ind * ps.ind_size) + 1
  286.     : *s_lab == '#' ? 1
  287.     : ps.ind_size * (ps.ind_level - label_offset) + 1;
  288. }
  289.  
  290.  
  291. /*
  292.  * Copyright (C) 1976 by the Board of Trustees of the University of Illinois 
  293.  *
  294.  * All rights reserved 
  295.  *
  296.  *
  297.  * NAME: fill_buffer 
  298.  *
  299.  * FUNCTION: Reads one block of input into input_buffer 
  300.  *
  301.  * HISTORY: initial coding     November 1976    D A Willcox of CAC 1/7/77 A
  302.  * Willcox of CAC    Added check for switch back to partly full input
  303.  * buffer from temporary buffer 
  304.  *
  305.  */
  306. void
  307.   fill_buffer()
  308. {                /* this routine reads stuff from the input */
  309.     int count;
  310.     register char *p;
  311.     register int i;
  312.     register FILE *f = input;
  313.  
  314.     if (bp_save != 0) {        /* there is a partly filled input buffer left */
  315.     buf_ptr = bp_save;    /* dont read anything, just switch buffers */
  316.     buf_end = be_save;
  317.     bp_save = be_save = 0;
  318.     if (buf_ptr < buf_end)
  319.         return;        /* only return if there is really something
  320.                  * in this buffer */
  321.     }
  322.     p = in_buffer;
  323.     buf_ptr = p;
  324.     while ((*p++ = i = getc(f)) != EOF && i != '\n');
  325.     if (i == EOF) {
  326.     p[-1] = ' ';
  327.     *p++ = '\n';
  328.     had_eof = true;
  329.     }
  330.     buf_end = p;
  331.     if (p[-2] == '/' && p[-3] == '*') {
  332.     if (in_buffer[3] == 'I' && strncmp(in_buffer, "/**INDENT**", 11) == 0)
  333.         fill_buffer();    /* flush indent error message */
  334.     else {
  335.         int com = 0;
  336.  
  337.         p = in_buffer;
  338.         while (*p == ' ' || *p == '\t')
  339.         p++;
  340.         if (*p == '/' && p[1] == '*') {
  341.         p += 2;
  342.         while (*p == ' ' || *p == '\t')
  343.             p++;
  344.         if (p[0] == 'I' && p[1] == 'N' && p[2] == 'D' && p[3] == 'E'
  345.             && p[4] == 'N' && p[5] == 'T') {
  346.             p += 6;
  347.             while (*p == ' ' || *p == '\t')
  348.             p++;
  349.             if (*p == '*')
  350.             com = 1;
  351.             else if (*p == 'O')
  352.             if (*++p == 'N')
  353.                 p++, com = 1;
  354.             else if (*p == 'F' && *++p == 'F')
  355.                 p++, com = 2;
  356.             while (*p == ' ' || *p == '\t')
  357.             p++;
  358.             if (p[0] == '*' && p[1] == '/' && p[2] == '\n' && com) {
  359.             if (s_com != e_com || s_lab != e_lab || s_code != e_code)
  360.                 dump_line();
  361.             if (!(inhibit_formatting = com - 1)) {
  362.                 n_real_blanklines = 0;
  363.                 postfix_blankline_requested = 0;
  364.                 prefix_blankline_requested = 0;
  365.                 suppress_blanklines = 1;
  366.             }
  367.             }
  368.         }
  369.         }
  370.     }
  371.     }
  372.     if (inhibit_formatting) {
  373.     p = in_buffer;
  374.     do
  375.         putc(*p, output);
  376.     while (*p++ != '\n');
  377.     }
  378.     return;
  379. };
  380.  
  381. /*
  382.  * Copyright (C) 1976 by the Board of Trustees of the University of Illinois 
  383.  *
  384.  * All rights reserved 
  385.  *
  386.  *
  387.  * NAME: pad_output 
  388.  *
  389.  * FUNCTION: Writes tabs and spaces to move the current column up to the desired
  390.  * position. 
  391.  *
  392.  * ALGORITHM: Put tabs and/or blanks into pobuf, then write pobuf. 
  393.  *
  394.  * PARAMETERS: current        integer        The current column target
  395.  * nteger        The desired column 
  396.  *
  397.  * RETURNS: Integer value of the new column.  (If current >= target, no action
  398.  * is taken, and current is returned. 
  399.  *
  400.  * GLOBALS: None 
  401.  *
  402.  * CALLS: write (sys) 
  403.  *
  404.  * CALLED BY: dump_line 
  405.  *
  406.  * HISTORY: initial coding     November 1976    D A Willcox of CAC 
  407.  *
  408.  */
  409. int pad_output(current, target)    /* writes tabs and blanks (if necessary) to
  410.                  * get the current output position up to the
  411.                  * target column */
  412.     int current;        /* the current column value */
  413.     int target;            /* position we want it at */
  414. {
  415.     register int curr;        /* internal column pointer */
  416.     register int tcur;
  417.     int t_target;
  418.  
  419.     if (troff)
  420.     fprintf(output, "\\h'|%dp'", (target - 1) * 7);
  421.     else {
  422.     if (current >= target)
  423.         return (current);    /* line is already long enough */
  424. #if 0
  425.     curr = current;
  426.     while ((tcur = ((curr - 1) & tabmask) + tabsize + 1) <= target) {
  427.         putc('\t', output);
  428.         curr = tcur;
  429.     }
  430.     while (curr++ < target)
  431.         putc(' ', output);    /* pad with final blanks */
  432. #else
  433.     t_target = target - 1;
  434.     current--;
  435.     tcur = t_target - (t_target % tabsize);        /* align it on a tabstop */
  436.     curr = (current - (current % tabsize));
  437.     curr = tcur - curr;
  438.     curr /= tabsize;
  439.     while (curr--)
  440.         putc('\t', output);
  441.     curr = t_target - tcur;
  442.     while (curr--)
  443.         putc(' ', output);
  444. #endif
  445.     }
  446.     return (target);
  447. };
  448.  
  449. /*
  450.  * Copyright (C) 1976 by the Board of Trustees of the University of Illinois 
  451.  *
  452.  * All rights reserved 
  453.  *
  454.  *
  455.  * NAME: count_spaces 
  456.  *
  457.  * FUNCTION: Find out where printing of a given string will leave the current
  458.  * character position on output. 
  459.  *
  460.  * ALGORITHM: Run thru input string and add appropriate values to current
  461.  * position. 
  462.  *
  463.  * RETURNS: Integer value of position after printing "buffer" starting in column
  464.  * "current". 
  465.  *
  466.  * HISTORY: initial coding     November 1976    D A Willcox of CAC 
  467.  *
  468.  */
  469. int
  470.   count_spaces(current, buffer)
  471. /*
  472.  * this routine figures out where the character position will be after
  473.  * printing the text in buffer starting at column "current" 
  474.  */
  475.     int current;
  476.     char *buffer;
  477. {
  478.     register char *buf;        /* used to look thru buffer */
  479.     register int cur;        /* current character counter */
  480.  
  481.     cur = current;
  482.  
  483.     for (buf = buffer; *buf != '\0'; ++buf) {
  484.     switch (*buf) {
  485.  
  486.         case '\n':
  487.         case '\f':        /* form feed */
  488.         cur = 1;
  489.         break;
  490.  
  491.         case '\t':
  492. #if 0
  493.         cur = ((cur - 1) & tabmask) + tabsize + 1;
  494. #else
  495.         cur += tabsize - (cur % tabsize) + 1;
  496. #endif
  497.         break;
  498.  
  499.         case '\b':        /* this is a backspace */
  500.         --cur;
  501.         break;
  502.  
  503.         default:
  504.         ++cur;
  505.         break;
  506.     }            /* end of switch */
  507.     }                /* end of for loop */
  508.     return (cur);
  509. };
  510.  
  511. #ifdef __STDC__
  512. void diag(int level, char *msg,...)
  513. #else
  514. void diag(va_alist)
  515.   va_decl
  516. #endif
  517. {
  518.     va_list mark;
  519. #ifndef __STDC__
  520.     int level;
  521.     int msg;
  522.     char *msg;
  523.     va_start(mark);
  524.     level = va_arg(mark, int);
  525.     msg = va_arg(mark, char *)
  526. #else
  527.     va_start(mark, msg);
  528. #endif
  529.  
  530.     if (output == stdout) {
  531.     fprintf(stdout, "/**INDENT** %s(%d): ", level == 0 ? "Warning" : "Error", line_no);
  532.     vfprintf(stdout, msg, mark);
  533.     fprintf(stdout, " */\n");
  534.     } else {
  535.     fprintf(stderr, "%s(%d): ", level == 0 ? "Warning" : "Error", line_no);
  536.     vfprintf(stderr, msg, mark);
  537.     fprintf(stderr, "\n");
  538.     }
  539.     va_end(mark);
  540. }
  541.